package gateway

import (
	"fmt"
	"github.com/smallnest/rpcx/protocol"
	"gogame/gameservice/service"
	"gogame/logger"
	"gogame/server/rpcx"
	"gogame/server/rpcx/client"
	"runtime/debug"
)

type name2Func map[string]func(*protocol.Message)

type RpcManage struct {
	service            service.IService
	name               string
	sender             *Sender                       // 消息推送
	serviceName2Client map[string]*client.RpcXClient // 服务对应的rpcXClient
	serviceName2Method map[string]name2Func          // 服务对应的func
}

// NewRpcManage 创建rpcManage
func NewRpcManage(service service.IService) *RpcManage {
	return &RpcManage{
		sender:             NewSender(service),
		serviceName2Client: make(map[string]*client.RpcXClient),
		serviceName2Method: make(map[string]name2Func),
	}
}

// GetDefaultServiceNameList 获取默认rpcX服务列表
func (r *RpcManage) GetDefaultServiceNameList() []string {
	_defaultServerNameList := []string{
		rpcx.GetDefaultServiceName(),
	}
	return _defaultServerNameList
}

// Run 开启
func (r *RpcManage) Run(name, listen string, serviceNameList ...string) {
	r.name = name

	// 默认开启api服务
	if len(serviceNameList) == 0 {
		serviceNameList = r.GetDefaultServiceNameList()
	}
	for _, serviceName := range serviceNameList {
		// client服务方法注册
		r.serviceName2Method[serviceName] = r.sender.RegisterFunc(serviceName)

		// new rpcXClient
		r.serviceName2Client[serviceName] = client.NewRpcXClient(listen, serviceName, r.DoMessage)
		r.serviceName2Client[serviceName].Dial(true)
	}
}

// Stop 停止
func (r *RpcManage) Stop() {
	r.sender.Stop()
	for _, rpcxClient := range r.serviceName2Client {
		rpcxClient.Close()
	}
	r.serviceName2Client = nil
}

// GetRpcXClient 获取一个rpcXClient
func (r *RpcManage) GetRpcXClient(key string) *client.RpcXClient {
	_rpcXClient, _ok := r.serviceName2Client[key]
	if !_ok {
		return nil
	}
	return _rpcXClient
}

// SetUser 设置玩家uid对应的链接对象
func (r *RpcManage) SetUser(conn *GatewayApp) {
	r.sender.SetUser(conn)
}

// DelUser 移除玩家uid对应的链接对象
func (r *RpcManage) DelUser(conn *GatewayApp) {
	r.sender.DelUser(conn)
}

// DoMessage 处理rpcXServer推送过来的消息
func (r *RpcManage) DoMessage(msg *protocol.Message) {
	defer func() {
		if r := recover(); r != nil {
			errMsg := fmt.Sprintf(
				"rpcmanage.DoMessage error!!\nmsg:%+v\nerr--->: 【%s】\n%s\n",
				msg,
				r.(error).Error(),
				debug.Stack(),
			)
			logger.GatewayLog.Error(errMsg)
		}
	}()

	_name2Func, _ok := r.serviceName2Method[msg.ServicePath]
	// 服务不存在
	if !_ok {
		logger.GatewayLog.Warn(fmt.Sprintf("DoMessage 【%s】 not exists!", msg.ServicePath))
		return
	}

	_func, _ok := _name2Func[msg.ServiceMethod]
	// 方法不存在
	if !_ok {
		logger.GatewayLog.Warn(fmt.Sprintf("DoMessage 【%s】【%s】  method not exists!", msg.ServicePath, msg.ServiceMethod))
		return
	}

	_func(msg)
}
